Skip to content

Conversation

@iamgabrielma
Copy link
Contributor

@iamgabrielma iamgabrielma commented Oct 19, 2022

Part of #7741
Branched from #7848 , that PR needs to be merged first.

Description

This PR implements the basic UI for searching Customers. The scope of this PR is limited to display a search view when we tap on the search icon, display Customer results matching our keyword, and pass the Customer data back to our EditOrderAddressForm view when we tap in any of the Customers. Filling the data to corresponding fields will be done in a future PR.

Changes

  • Adds a OrderCustomerListView, which is a SwiftUI wrapper for the existing SearchViewController.
  • Adds a CustomerSearchUICommand class, which is the implementation of the existing SearchUICommand for Customer search.

Testing instructions

  1. Go to Orders > + > Create new Order > + Add Customer details > Tap on the magnifying glass icon:

  1. Search for a Customer name, and tap on it:

  1. Check if details are printed in the Xcode console. This will display steps 1 to 4, which represents the Customer data flow to EditOrderAddressForm, which we'll use to fill the Order with Customer details in a future PR.
1 - Customer tapped
2 - Customer ID: 5 - Name: Hello)
3 - Customer Callback. Fill Order data with Customer details
4 - Customer ID: 5 - Name: Hello)

@iamgabrielma iamgabrielma added type: enhancement A request for an enhancement. category: parity Match what's supported by the other platform. feature: order creation All tasks related to creating an order labels Oct 19, 2022
@iamgabrielma iamgabrielma added this to the 10.9 milestone Oct 19, 2022
@iamgabrielma iamgabrielma mentioned this pull request Oct 19, 2022
15 tasks
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Oct 19, 2022

You can test the changes from this Pull Request by:
  • Clicking here or scanning the QR code below to access App Center
  • Then installing the build number pr7880-da5e401 on your iPhone

If you need access to App Center, please ask a maintainer to add you.

@iamgabrielma iamgabrielma changed the base branch from trunk to issue/7741-add-customer-upsert-logic October 20, 2022 02:01
@iamgabrielma iamgabrielma marked this pull request as ready for review October 20, 2022 03:20
final class CustomerSearchUICommand: SearchUICommand {

typealias Model = Customer
typealias CellViewModel = TitleAndSubtitleAndStatusTableViewCell.ViewModel
Copy link
Contributor Author

@iamgabrielma iamgabrielma Oct 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to get a different recommendation for the CellView we want to use here, at the moment I'm using TitleAndSubtitleAndStatusTableViewCell just for convenience, as must conform to SearchResultCell there are several options to choose from without having to create a new one (or I could create a new one as well!)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that you're going to have the avatar in there too, you might want to try adding SearchResultCell conformance to LeftImageTitleSubtitleTableViewCell?

The only thing it won't do is any attributed text in the subtitle for an underlined email as on Android... but I don't personally think that should be a blocker.

Base automatically changed from issue/7741-add-customer-upsert-logic to trunk October 21, 2022 15:16
@spencertransier spencertransier modified the milestones: 10.9, 11.0 Oct 22, 2022
@iamgabrielma iamgabrielma mentioned this pull request Oct 24, 2022
3 tasks
@iamgabrielma
Copy link
Contributor Author

@rachelmcr @ThomazFB @Ecarrion please leave a comment if any of you plan to review the PR today, otherwise I'll review it with @joshheald during our pairing session. Thanks!

}

func searchResultsPredicate(keyword: String) -> NSPredicate? {
return NSPredicate(format: "ANY searchResults.keyword = %@", keyword)
Copy link
Contributor Author

@iamgabrielma iamgabrielma Oct 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to add siteID! We'll add it in a future PR/commit as this is currently behind a feature flag.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! Don't forget both places, this is the one for the CustomerSearchResults rather than the Customer

Copy link
Contributor Author

@iamgabrielma iamgabrielma Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely, I went ahead and changed it in this PR as was a quick one: a8dd778

Copy link
Contributor

@joshheald joshheald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done. I was able to test it and get some search results showing in the app.

The comments here can all be addressed in a future PR, nothing is blocking.

Other general things I noticed, outside the scope of this PR, for your notes:

  1. There are lots of network requests to /wc/v3/customers/0, which will always fail, these could be filtered out.
  2. There's no empty state yet, just a blank white screen.
  3. The search doesn't behave the same as on Android. On Android, search looks at the email field only, and on iOS, it looks at the name fields only. Apologies if I'm forgetting some context here, if Android are going to change that...

:shipit:

final class CustomerSearchUICommand: SearchUICommand {

typealias Model = Customer
typealias CellViewModel = TitleAndSubtitleAndStatusTableViewCell.ViewModel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that you're going to have the avatar in there too, you might want to try adding SearchResultCell conformance to LeftImageTitleSubtitleTableViewCell?

The only thing it won't do is any attributed text in the subtitle for an underlined email as on Android... but I don't personally think that should be a blocker.

4598298028574688003A9AFE /* Inject */ = {
isa = XCSwiftPackageProductDependency;
package = 4598297F28574688003A9AFE /* XCRemoteSwiftPackageReference "Inject.git" */;
package = 4598297F28574688003A9AFE /* XCRemoteSwiftPackageReference "Inject" */;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has Inject changed for any particular reason? What happens if you revert these changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! And that's a good question:

The only difference I'm seeing is that when I revert the changes is that I can see the iOS 15.0 minimum support warnings for YosemiteTests related to kUTTypeJPEG deprecation.

This most likely comes from me switching to iOS15 temporarily when working on this, as at the same time we were upgrading the app minimum version for the app and I wanted to see if my changes came with potential deprecations. Then when I switched back to iOS14, I may have missed the changes in project.pbxproj.

I see these changes are part of trunk already, but I reverted here: da5e401 as this change shouldn't go with my PR anyway 👍

func createResultsController() -> ResultsController<StorageCustomer> {
let storageManager = ServiceLocator.storageManager
let descriptor = NSSortDescriptor(keyPath: \StorageCustomer.customerID, ascending: false)
return ResultsController<StorageCustomer>(storageManager: storageManager, sortedBy: [descriptor])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will display StorageCustomers from Core Data for any site, not just the current one, which could lead to confusion for some merchants with multiple stores.

If you add a predicate specifying the siteID, that should resolve the issue. No need to block this PR since it's behind a feature flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I committed the changes a8dd778 with this one as we went through these in our pairing as was pretty quick 👍

func createCellViewModel(model: Customer) -> TitleAndSubtitleAndStatusTableViewCell.ViewModel {
return CellViewModel(
id: "\(model.customerID)",
title: "\(model.firstName ?? "") \(model.lastName ?? "")",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This... might be the right thing to do given our data source, but names are complicated, and simply concatenating them isn't correct in all locales.

See PersonNameComponentsFormatter docs for more info. There's not necessarily anything to do here (as I don't know whether we have enough in our data source to correctly make a formatter) but I thought it would be useful for you to know about if you don't already.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the link, I definitely didn't know about PersonNameComponentsFormatter. I agree with you, concatenating strings doesn't look good to me either and I'll look for cleaner alternatives (if possible). I'll dig into this document and make any necessary improvements on another PR.

id: "\(model.customerID)",
title: "\(model.firstName ?? "") \(model.lastName ?? "")",
subtitle: model.email,
accessibilityLabel: "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility Label is required here... see what it does in VoiceOver without it: it just announces:

Button

Without any detail about the name of the user or anything else about the search result.

If you're moving to another cell, you may not have to do anything, usually we get VoiceOver in cells for free, but in this case we are specific about what the label should be in the view model.

}

func searchResultsPredicate(keyword: String) -> NSPredicate? {
return NSPredicate(format: "ANY searchResults.keyword = %@", keyword)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! Don't forget both places, this is the one for the CustomerSearchResults rather than the Customer

Comment on lines +14 to +16
var searchBarAccessibilityIdentifier: String = "customer-search-screen-search-field"

var cancelButtonAccessibilityIdentifier: String = "customer-search-screen-cancel-button"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably only need to set accessibilityIdentifiers if you're actually using the search in a UI test. Identifiers are nothing to do with VoiceOver and other assistive tech, in practice, they are only used for UI tests.

AccessibilityLabels are for VoiceOver and important to have on custom controls or complex groups.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL!

@joshheald
Copy link
Contributor

General observation: from my test site, the feature feels a bit... frustrating, in terms of the search results it can actually return. This is just a limitation of the API AFAIK, but I have lots of customer details on different orders, where the customers checked out as guests. In the Analytics section of wc-admin, it manages to link things together for those customers, even though they're guests... it certainly would be good if we could do a bit more like that for filling address details!

The brief here is to get to parity with Android, but if you do have thoughts or findings which could feed in to an iteration 2 of the feature, it would be good to hear them...

@iamgabrielma
Copy link
Contributor Author

The search doesn't behave the same as on Android. On Android, search looks at the email field only, and on iOS, it looks at the name fields only. Apologies if I'm forgetting some context here, if Android are going to change that...

Yes, this was one of the API limitations when taking this approach (pe5pgL-3r-p2)

One big problem: search doesn’t search names, phones, and emails at the same time. You’ll have to use searchby and define what field you want to search.

I believe that, depending on when we plan to change the API behaviour, we could use this to our advantage and create some sort of "advanced search" with searchBy, which would also improve your point about the search feature being frustrating, which I agree with.

@iamgabrielma iamgabrielma merged commit 0ba7063 into trunk Oct 26, 2022
@iamgabrielma iamgabrielma deleted the issue/741-implement-customer-search-ui branch October 26, 2022 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: parity Match what's supported by the other platform. feature: order creation All tasks related to creating an order type: enhancement A request for an enhancement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants